<!-- 聊天框 -->
<template>
  <div class="m-0">
    <div v-if="!renderValues.center"
         class="col-12 relative"
         :style="renderValues.left ? 'text-align: left': 'text-align: right'">
      <div class="chat"
           ref="chat"
           :style="renderValues.right ? {backgroundColor: '#98E165',right: '35px'} : {backgroundColor: 'white', left: '35px'}">
        <!-- 聊天内容 -->
        <span @click="spanClickHandler($event)" v-html="renderValues.context"></span>
        <!-- 箭头 -->
        <div :class="arrowClass"></div>
      </div>
      <!-- 头像 -->
      <div class="avatar-left" v-if="renderValues.left">
        <Avatar size="large"
                v-if="renderValues.avatar"
                :image="renderValues.avatar"/>
        <Avatar size="large" v-else :label="renderValues.name.substring(0,1).toUpperCase()">
        </Avatar>
      </div>
      <div class="avatar-right" v-if="renderValues.right">
        <Avatar size="large"
                v-if="renderValues.avatar"
                :image="renderValues.avatar"/>
        <Avatar size="large" v-else :label="renderValues.name.substring(0,1).toUpperCase()">
        </Avatar>
      </div>
    </div>
    <div v-else class="col-12 exit">
      {{ renderValues.context }}
    </div>
  </div>
</template>

<script lang="ts" setup>
/** JS */
import {ref, reactive, defineProps, Ref, watch, onMounted, nextTick, defineEmits} from 'vue';

interface ChatPanel {
  /** 头像 */
  avatar?: string
  /** 居中 */
  center?: boolean
  /** 居左 */
  left?: boolean
  /** 居右 */
  right?: boolean
  /** 姓名 */
  name: string
  /** 聊天内容 */
  context: string
}

type Arrow = {
  trigger: string
  arrow: string
}

/** 判断箭头方向 */
function judgeArrow(tip) {
  let arrow: Arrow = {
    trigger: 'triangle-right',
    arrow: 'arrow-right'
  }
  if (tip === 'right') {
    arrow = {trigger: 'triangle-right', arrow: 'arrow-right'}
  }
  if (tip === 'left') {
    arrow = {trigger: 'triangle', arrow: 'arrow'};
  }
  return arrow;
}

/** 钩子 */
const props = defineProps<ChatPanel>();
const chat = ref(null);
const $ = require("jquery"), emits = defineEmits(['imgClick'])

/** 渲染钩子 */
const renderValues: ChatPanel = {
      avatar: props.avatar,
      center: props.center,
      left: props.left,
      right: props.right,
      name: props.name,
      context: props.context
    },
    renderParams = reactive({
      // 图片预览
      imgPreview: false,
      // 图片地址
      imgSrc: '',
      // 图片宽度
      imgWidth: 0,
      // 最大宽度
      imgMaxWidth: 0
    });
// 箭头样式
let arrowClass: Ref<string> = ref('');
if (props.right) {
  let clazz: Arrow = judgeArrow('right');
  arrowClass.value = clazz.trigger;
}
if (props.left) {
  let clazz: Arrow = judgeArrow('left');
  arrowClass.value = clazz.trigger;
}
// 动态监听
watch(props, (n) => {
  for (let key in renderValues) {
    renderValues[key]['value'] = n[key];
  }
  if (n.right) {
    let clazz = judgeArrow('right');
    arrowClass.value = clazz.trigger;
  }
  if (n.left) {
    let clazz = judgeArrow('left');
    arrowClass.value = clazz.trigger;
  }
})

onMounted(() => {
  const $chat = $(chat.value);
  nextTick(() => {
    const span = $chat.children('span');
    if (span.children()[0]) {
      const $span = $(span);
      if ($span.find('*').length > 0) {
        $span.find('*:not(div,span)').css({
          wordBreak: 'break-all',
          whiteSpace: 'pre-wrap',
          padding: '5px',
          borderRadius: '5px'
        })
      }
    }
  })
});

/** 点击 span 判断是否为图片*/
const spanClickHandler = (event) => {
  if (event.target.nodeName === 'IMG') {
    renderParams.imgSrc = event.target.src;
    renderParams.imgPreview = true;
    let width = event.target.naturalWidth;
    if (width > 1000) {
      renderParams.imgWidth = 1000;
    } else {
      renderParams.imgWidth = width;
    }
    renderParams.imgMaxWidth = width;
    emits('imgClick', event.target);
  }
}
</script>

<style lang="less" scoped>
.text-img {
  height: auto;
  width: auto;
  max-width: 350px;
}

.chat {
  display: inline-block;
  position: relative;
  max-width: 350px;
  padding: 10px 8px;
  margin-top: 10px;
  margin-left: 15px;
  margin-right: 15px;
  border-radius: 5px;
  word-break: break-all;
  white-space: pre-wrap;
}

.chat span, .chat div, .chat pre {
  word-break: break-all !important;
  white-space: pre-wrap !important;
}

.avatar-right {
  position: absolute;
  right: 1px;
  top: 10px;

  &:hover {
    cursor: pointer;
  }
}

.avatar-left {
  position: absolute;
  left: 1px;
  top: 10px;

  &:hover {
    cursor: pointer;
  }
}

.triangle,
.triangle-right {
  position: absolute;
  top: 10px;
  border-width: 10px;
  border-style: solid;
}

.triangle {
  left: -15px;
  border-color: transparent white transparent transparent;
}

.triangle-right {
  right: -15px;
  border-color: transparent transparent transparent #98E165;
}

.exit {
  text-align: center;
  color: #BDBDBD
}

img {
  max-width: 100px;
}
</style>
